package com.gitee.demo.httpclient;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gitee.demo.constants.HttpHeaderContentTypeEnum;
import com.gitee.demo.httpsSSL.SSLClient;
import com.gitee.demo.utils.HttpsUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.gitee.demo.httpsSSL.SSLClient.trustAllHttpsCertificates;

/**
 * HttpClient发送GET、POST请求
 *
 * @author Tao on 2019/12/6
 */

public class MyHttpsClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyHttpsClient.class);

    /**
     * 返回成功状态码
     */
    private static final int SUCCESS_CODE = 200;

    private static HostnameVerifier hv = new HostnameVerifier() {
        public boolean verify(String urlHostName, SSLSession session) {
            System.out.println("Warning: URL Host: " + urlHostName + " vs. "
                    + session.getPeerHost());
            return true;
        }
    };


    /**
     * 发送GET请求
     *
     * @param url       请求url
     * @param paramsMap 请求参数
     * @return JSON或者字符串
     * @throws Exception
     */
    public static Object sendGetHttps(String url, Map<String, Object> paramsMap, Map<String, String> headersMap) throws Exception {
        JSONObject jsonObject = null;
        HttpClient client = new SSLClient();
        HttpResponse response = null;


        try {
            //取消页面ssl验证
            trustAllHttpsCertificates();
            HttpsURLConnection.setDefaultHostnameVerifier(hv);

            /**
             * 创建URIBuilder 设置参数
             */
            URIBuilder uriBuilder = new URIBuilder(url);
            List<NameValuePair> paramsList = HttpsUtils.convertToNameValuePairList(paramsMap);
            uriBuilder.addParameters(paramsList);
            /**
             * 创建HttpGet
             */
            HttpGet httpGet = new HttpGet(uriBuilder.build());

            /**
             * 设置消息头
             */
            httpGet.setHeaders(HttpsUtils.mapConvertToHeaders(headersMap));
            /**
             * 请求服务
             */
            response = client.execute(httpGet);
            /**
             * 获取响应吗
             */
            int statusCode = response.getStatusLine().getStatusCode();

            if (SUCCESS_CODE == statusCode) {
                /**
                 * 获取返回对象
                 */
                HttpEntity entity = response.getEntity();
                /**
                 * 通过EntityUitls获取返回内容
                 */
                String result = EntityUtils.toString(entity, "UTF-8");
                /**
                 * 转换成json,根据合法性返回json或者字符串
                 */
                try {
                return result;


//                    jsonObject = JSONObject.parseObject(result);
//                    return jsonObject;
                } catch (Exception e) {
                    return result;
                }
            } else {
                LOGGER.error("HttpClientService-line: {}, errorMsg{}", 97, "GET请求失败！");
            }
        } catch (Exception e) {
            LOGGER.error("HttpClientService-line: {}, Exception: {}", 100, e);
        } finally {
        }
        return null;
    }

    /**
     * 发送POST请求
     *
     * @param url
     * @param paramsMap x-www-form-urlencoded
     * @return JSON或者字符串
     * @throws Exception
     */
    public static Object sendPostHttps(String url, Map<String, Object> paramsMap, Map<String, String> headersMap, String headerContentType) throws Exception {
        JSONObject jsonObject = null;
        HttpClient client = new SSLClient();
        HttpResponse response = null;

        try {
            //取消验证ssl有效性 原因是https证书问题，java抓取时忽略掉证书才能访问。jsoup在调用前先执行下以下忽略证书请求就可以了。
            trustAllHttpsCertificates();
            HttpsURLConnection.setDefaultHostnameVerifier(hv);
            /**
             * 创建一个post对象
             */
            HttpPost post = new HttpPost(url);

            /**
             * 包装成一个Entity对象
             */
            HttpHeaderContentTypeEnum headerContentTypeEnum = HttpHeaderContentTypeEnum.convert(headerContentType);
            if (HttpHeaderContentTypeEnum.JSON == headerContentTypeEnum) {
                StringEntity entity = new StringEntity(JSON.toJSONString(paramsMap), "UTF-8");
                entity.setContentType("application/json");
                post.setEntity(entity);
            } else if (HttpHeaderContentTypeEnum.X_WWW_FORM == headerContentTypeEnum) {
                List<NameValuePair> paramsList = HttpsUtils.convertToNameValuePairList(paramsMap);
                StringEntity entity = new UrlEncodedFormEntity(paramsList, "UTF-8");
                post.setEntity(entity);
            }

            /**
             * 设置请求的报文头部的编码
             */
            post.setHeaders(HttpsUtils.mapConvertToHeaders(headersMap));


            /**
             * 执行post请求
             */
            response = client.execute(post);
            /**
             * 获取响应码
             */
            int statusCode = response.getStatusLine().getStatusCode();
            if (SUCCESS_CODE == statusCode) {
                /**
                 * 通过EntityUitls获取返回内容
                 */
                String result = EntityUtils.toString(response.getEntity(), "UTF-8");
                /**
                 * 转换成json,根据合法性返回json或者字符串
                 */
                try {
                    jsonObject = JSONObject.parseObject(result);
                    return jsonObject;
                } catch (Exception e) {
                    return result;
                }
            } else {
                LOGGER.error("HttpClientService-line: {}, errorMsg：{}", 146, "POST请求失败！");
            }
        } catch (Exception e) {
            LOGGER.error("HttpClientService-line: {}, Exception：{}", 149, e);
        } finally {

        }
        return null;
    }


    /**
     * 通过请求第三方接口验证token
     *
     * @param token
     */
    public static String verifyToken(String token, String verifyUrl) throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        Map result = null;
        httpClient = HttpClients.createDefault();
        //参数
        Map params = new HashMap();
        params.put("userToken", token);
        params.put("type", "floodForecast");

        //取消验证ssl有效性 原因是https证书问题，java抓取时忽略掉证书才能访问。jsoup在调用前先执行下以下忽略证书请求就可以了。
        trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(hv);

        //通过post方式访问
        HttpPost post = new HttpPost(verifyUrl);
        StringEntity paramEntity = new StringEntity(JSON.toJSONString(params), "UTF-8");
        paramEntity.setContentType("application/json");
        post.setEntity(paramEntity);
        response = httpClient.execute(post);
        HttpEntity valueEntity = response.getEntity();
        String content = EntityUtils.toString(valueEntity);

        return content;
    }

    /**
     * 将InputStream写入本地文件
     * @param destination 写入本地目录
     * @param input 输入流
     * @throws IOException IOException
     */
    public static void writeToLocal(String destination, String result)
            throws IOException {

        InputStream input=null;


        byte[] bytes1 = result.getBytes("utf-8");


        int index;
        byte[] bytes = new byte[1024];
        FileOutputStream downloadFile = new FileOutputStream(destination);
        while ((index = input.read(bytes)) != -1) {
            downloadFile.write(bytes, 0, index);
            downloadFile.flush();
        }
        input.close();
        downloadFile.close();

    }

}
